/*
 *
 *
Copyright (c) 1998-2001 Aristar, Inc. All rights reserved.

Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:

1. Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.

2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.

3. The end-user documentation included with the redistribution, if any,
must include the following acknowledgment:

"This product includes software developed by Aristar, Inc. (http://www.aristar.com/)."

Alternately, this acknowledgment may appear in the software itself, if and
wherever such third-party acknowledgments normally appear.

4. The names "Dialect" and "Aristar, Inc." must not be used to endorse or
promote products derived from this software without prior written permission.
For written permission, please contact info@aristar.com.

5. Products derived from this software may not be called "Dialect", nor may
"Dialect" appear in their name, without prior written permission of Aristar, Inc.

THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESSED OR IMPLIED WARRANTIES,
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
ARISTAR, INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

This software consists of voluntary contributions made by many individuals
on behalf of Aristar, Inc.  For more information on Aristar, Inc.,
please see <http://www.aristar.com/>.

Portions of this software are based upon software freely available and
written by individuals not associated with Aristar, Inc.  Copyrights are
maintained in the relevant source code files.
 *
 *
 */

#ifndef _CBYTECODE__H__
#define _CBYTECODE__H__

#include "DConfigGlobals.h"
#include "CTokenTypes.h"
#include "TFile.h"

class CByteCode;	// Forward
TString TokToString(const CByteCode& token);	// For debug purposes

///////////////////////////////////////////////////////////

class CByteCode {
public:
	CByteCode();
	CByteCode(CByteCode& in, TokenTypes headTok, TokenTypes tailTok);
	CByteCode(const CByteCode& copy);	// Clone the stream
	virtual ~CByteCode();

	bool CompileFile(TString filename);
	bool CompileText(LPCTSTR text, LPCTSTR moduleName);
	bool SaveToFile(TString filename);
	bool LoadFromFile(TString filename);
	bool LoadFromMemory(U8* buffer);

	int Length() const;
	const U8* Data() const;

	TString __unparse__();

	static U8* SerializeIn(U8* inBuffer, CByteCode** result);
	void SerializeOut(CFile* outFile);

	TString GetLastError() const;
	int LineNumber() const;				// Current Line Number (-1 == unknown)
	int LineNumberNoOffset() const;		// Used by interpreter loop statements only
	TString ModuleName();				// Name of module this code came from
	TString ModulePath();				// If known, full path of module this code came from
	long Position() const;				// Number of bytes since start of stream
	void Seek(long pos, int lineNum);	// Move stream to pos bytes from start
	void Rewind();

	void NextToken();
	inline CByteCode& operator++(){NextToken(); return *this;};	// Prefix increment
	CByteCode operator++(int);	// Postfix increment (DON'T USE THIS!!!)
	inline operator TokenTypes() const{return m_TokenType;};	// Typecast to return current token type
	inline operator LPCTSTR() const{return (LPCTSTR)m_StringResult;};
	inline operator int() const {return m_IntegerResult;};
	inline operator float() const {return m_FloatResult;};

protected:
	TString m_LastError;		// Last error reported by this instance
	TString m_ParentModule;		// Name of module this code came from
	TString m_Path;				// Path used when this module was loaded
	int m_LineNumber;			// Current line number being executed
	int m_LineOffset;			// Line number a function decl started on
	TokenTypes m_TokenType;		// Current token type

	int m_IntegerResult;		//
	float m_FloatResult;		// Values as useful to m_TokenType
	TString m_StringResult;		//

	long m_Index;				// Current location in m_CodeBuffer
	U8* m_CodeBuffer;			// Array of byte code
	long m_CodeBufferLength;	// Size in bytes of m_CodeBuffer

	/*
	 * The following remaining members are used only for compiling text
	 * buffers into the internal byte code (creating m_CodeBuffer)
	 */
	bool _Compile(LPCSTR text, LPCTSTR moduleName, TString path);	// Compile ASCII text buffer
	bool _Compile(LPCWSTR text, LPCTSTR moduleName, TString Path);	// Compile Unicode text buffer
	bool _StartNow(const char *text, int textLength);// Compile NOW!
	LPCSTR m_Text;

	char NextChar(bool bConvertCRLF = true);
	char m_ch0;
	char m_ch1;

	bool ParseIdent();
	bool ParseHexNumber();
	bool ParseNumber();
	bool ParseQuotedString();
	bool ParseBlockComment();
	bool ParseLineComment();
	bool ParseSpecial();
	bool m_bInQuotedString;

	inline bool CheckSpace(int bytes);	// Ensures m_CodeBuffer has enough room for bytes
	inline bool Store(TokenTypes x);
	inline bool Store(int x);
	inline bool Store(float x);
	inline bool Store(LPCSTR x, int length);
	inline bool Store(LPCWSTR x, int length);
	inline void Read(int& x);
	inline void Read(float& x);
};

///////////////////////////////////////////////////////////
#endif	// _CBYTECODE__H__
